package com.example.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.user.constants.JwtClaimsConstant;
import com.example.user.context.BaseContext;
import com.example.user.enums.RoleCode;
import com.example.user.mapper.UserMapper;
import com.example.user.pojo.dto.*;
import com.example.user.pojo.entity.User;
import com.example.user.pojo.vo.LoginVO;
import com.example.user.pojo.vo.UserVO;
import com.example.user.properties.JwtProperties;
import com.example.user.result.PageResult;
import com.example.user.result.Result;
import com.example.user.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.user.utils.JwtUtil;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author hxt
 * @since 2025-06-16
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    private final JwtProperties jwtProperties;

    /**
     *  用户注册
     * @param registerDTO 注册信息
     * @return 是否成功
     */
    public Result<String> register(RegisterDTO registerDTO) {
        User user = new User();
        user.setUsername(registerDTO.getUsername());
        user.setPassword(DigestUtils.md5DigestAsHex(registerDTO.getPassword().getBytes()));
        user.setEmail(registerDTO.getEmail());
        user.setPhone(registerDTO.getPhone());
        boolean save = this.save(user);
        //TODO 设置默认权限角色
        //TODO 向日志服务发送注册消息
        if (save) {
            return Result.success("注册成功");
        }else {
            return Result.error("注册失败");
        }
    }

    /**
     *  用户登录
     * @param loginDTO 登录信息
     * @return 登录结果
     */
    public Result<LoginVO> login(LoginDTO loginDTO) {
        //获取用户信息
        User user = lambdaQuery()
                .eq(User::getUsername, loginDTO.getUsername())
                .eq(User::getPassword, DigestUtils.md5DigestAsHex(loginDTO.getPassword().getBytes()))
                .one();
        if (user == null){
            return Result.error("用户名或密码错误");
        }
        //TODO 调用Permission服务获取用户权限

        //生成jwt
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.USER_ID, user.getUserId());
        claims.put(JwtClaimsConstant.USER_ROLE, "USER");
        String jwt = JwtUtil.createJWT( jwtProperties.getUserSecretKey(), jwtProperties.getUserTtl(), claims);

        //封装vo并返回
        LoginVO loginVO = new LoginVO();
        loginVO.setToken(jwt);
        loginVO.setId(user.getUserId());
        loginVO.setUserName(user.getUsername());
        //TODO 向日志服务发送消息
        return Result.success(loginVO);
    }

    /**
     *  用户列表
     * @param pageQueryDTO 分页参数
     * @return 用户列表
     */
    public Result<PageResult> userPageQuery(PageQueryDTO pageQueryDTO) {
        //获取当前用户信息
        Map<String, Object> currentUser = BaseContext.getCurrentUser();
        Long userId = (Long) currentUser.get(JwtClaimsConstant.USER_ID);
        RoleCode roleCode = (RoleCode) currentUser.get(JwtClaimsConstant.USER_ROLE);
        List<Long> userIds = new ArrayList<>();
        userIds.add(userId);
        //TODO 根据不同权限获取用户id
        switch (roleCode){
            case SUPER_ADMIN:
                break;
            case ADMIN:
                break;
            default:
                break;
        }
        //分页查询用户
        Page<User> page = lambdaQuery()
                .in(User::getUserId, userIds)
                .page(new Page<>(pageQueryDTO.getPage(), pageQueryDTO.getPageSize()));
        //封装并返回
        List<UserVO> userVOS = BeanUtil.copyToList(page.getRecords(), UserVO.class);
        PageResult pageResult = new PageResult();
        pageResult.setTotal(page.getTotal());
        pageResult.setRecords(userVOS);
        //TODO 向日志服务发送消息
        return Result.success(pageResult);
    }

    /**
     *  根据id查询用户
     * @param userId 用户id
     * @return 用户信息
     */
    public Result<UserVO> getUserById(Long userId) {
        //获取当前用户信息
        Map<String, Object> currentUser = BaseContext.getCurrentUser();
        Long currentUserId = (Long) currentUser.get(JwtClaimsConstant.USER_ID);
        RoleCode currentRoleCode = (RoleCode) currentUser.get(JwtClaimsConstant.USER_ROLE);
        User user = null;
        //判断是否查询自己的信息
        if (!Objects.equals(userId, currentUserId)) {
            //若查询其他用户的信息，则判断权限
            //TODO 获取查询用户的权限
            RoleCode permissions = RoleCode.USER;
            //判断权限
            boolean hasPermissions = HasPermissions(currentRoleCode, permissions);
            if (!hasPermissions){
                return Result.error("无权限");
            }
        }
        //查询用户信息
        user = lambdaQuery()
                .eq(User::getUserId, userId)
                .one();
        //封装并返回
        UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
        //TODO 向日志服务发送消息
        return Result.success(userVO);
    }

    /**
     * 根据id修改用户信息
     * @param userId 用户id
     * @param updateDTO 修改信息
     * @return 是否成功
     */
    public Result<String> updateUser(Long userId, UpdateDTO updateDTO) {
        //获取当前用户信息
        Map<String, Object> currentUser = BaseContext.getCurrentUser();
        Long currentUserId = (Long) currentUser.get(JwtClaimsConstant.USER_ID);
        RoleCode currentRoleCode = (RoleCode) currentUser.get(JwtClaimsConstant.USER_ROLE);
        //判断是否修改自己的信息
        if (!Objects.equals(userId, currentUserId)) {
            //若修改其他用户信息，则判断权限
            //TODO 获取修改用户的权限
            RoleCode permissions = RoleCode.USER;
            //判断权限
            boolean hasPermissions = HasPermissions(currentRoleCode, permissions);
            if (!hasPermissions){
                return Result.error("无权限");
            }
        }
        User user = new User();
        user.setUserId(userId);
        user.setUsername(updateDTO.getUsername());
        user.setEmail(updateDTO.getEmail());
        user.setPhone(updateDTO.getPhone());
        boolean update = this.updateById(user);
        if (StrUtil.isNotBlank(updateDTO.getRoleCode())){
            boolean updateRole = editUserRole(userId, updateDTO.getRoleCode(), currentRoleCode);
        }
        return Result.success();
    }

    /**
     * 重置密码
     * @param resetPasswordDTO 重置密码相关数据
     * @return 是否成功
     */
    public Result<String> resetPassword(ResetPasswordDTO resetPasswordDTO) {
        //获取当前用户信息
        Map<String, Object> currentUser = BaseContext.getCurrentUser();
        Long currentUserId = (Long) currentUser.get(JwtClaimsConstant.USER_ID);
        RoleCode currentRoleCode = (RoleCode) currentUser.get(JwtClaimsConstant.USER_ROLE);
        if (!Objects.equals(resetPasswordDTO.getUserId(), currentUserId)) {
            //若修改其他用户信息，则判断权限
            //TODO 获取修改用户的权限
            RoleCode permissions = RoleCode.USER;
            //判断权限
            boolean hasPermissions = HasPermissions(currentRoleCode, permissions);
            if (!hasPermissions){
                return Result.error("无权限");
            }
        }
        User user = new User();
        user.setUserId(resetPasswordDTO.getUserId());
        user.setPassword(resetPasswordDTO.getPassword());
        boolean update = this.updateById(user);
        return Result.success();
    }

    private boolean editUserRole(Long userId, String roleCode, RoleCode currentRoleCode) {
        //若不是超管则无权限修改
        if ( !RoleCode.SUPER_ADMIN.equals(currentRoleCode)){
            return false;
        }
        if (RoleCode.USER.equals(roleCode)){
            //TODO 调用降级user接口
        }else if (RoleCode.ADMIN.equals(roleCode)){
            //TODO 升级为admin接口
        }
        return true;
    }

    private boolean HasPermissions(RoleCode currentRoleCode, RoleCode permissions) {
        if (RoleCode.SUPER_ADMIN.equals(currentRoleCode)){
            return true;
        }
        if (RoleCode.USER.equals(currentRoleCode)){
            return false;
        }
        return RoleCode.USER.equals(permissions);
    }
}
